﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace QDasTransfer.Classes
{
	public class FileHelper
	{
		/// <summary>
		/// Return the last N levels of path. If N is larger than the number L of steps of a path, N is then set to L.
		/// </summary>
		/// <param name="path"></param>
		/// <param name="N"></param>
		/// <returns></returns>
		public static string GetLastDirectory(string path, int N = 0)
		{
			N = N < 0 ? 65535 : N;
			if (path == null || path.Trim().Length == 0)
				return "";

			string[] folders = path.Trim().Split(new char[] { '\\', ':', '/' }, StringSplitOptions.RemoveEmptyEntries);
			StringBuilder sb = new StringBuilder();
			// sb.Append(folders[folders.Length - 1]);
			for (int i = 0; i < N && i < folders.Length - 1; i++)
			{
				sb.Insert(0, folders[folders.Length - 2 - i] + "\\");
			}

			if (sb.Length > 0)
				sb.Remove(sb.Length - 1, 1);

			return sb.ToString();
		}

		/// <summary>
		/// Append a suffix to the path. 
		/// <example>"C:\data\a.txt" + "_20171222" => "C:\data\a_20171222.txt"</example>
		/// </summary>
		/// <param name="path"></param>
		/// <param name="suffix"></param>
		/// <returns></returns>
		public static string AppendSuffix(string path, string suffix)
		{
			if (path == null || path.Trim().Length == 0)
				return "";
			string dir = Path.GetDirectoryName(path);
			string name = Path.GetFileNameWithoutExtension(path);
			string ext = Path.GetExtension(path);
			return string.Format("{0}\\{1}{2}{3}", dir, name, suffix, ext);
		}

		/// <summary>
		/// Append a prefix to the path.
		/// <example>"C:\data\a.txt" + "20171222_" => "C:\data\20171222_a.txt"</example>
		/// </summary>
		/// <param name="path"></param>
		/// <param name="suffix"></param>
		/// <returns></returns>
		public static string AppendPrefix(string path, string prefix)
		{
			if (path == null || path.Trim().Length == 0)
				return "";
			string dir = Path.GetDirectoryName(path);
			string name = Path.GetFileNameWithoutExtension(path);
			string ext = Path.GetExtension(path);
			return string.Format("{0}\\{1}{2}{3}", dir, prefix, name, ext);
		}

		/// <summary>
		/// Adds a four-digit id to the filename in front of its extention.
		/// </summary>
		/// <param name="outputfile"></param>
		/// <returns></returns>
		public static String AddIncreamentId(string outputfile)
		{
			int suffixid = 0;
			string folder = Path.GetDirectoryName(outputfile);
			string filename = Path.GetFileNameWithoutExtension(outputfile);
			string ext = Path.GetExtension(outputfile);

			while (File.Exists(outputfile))
			{
				suffixid++;
				outputfile = string.Format("{0}\\{1}_{2}{3}", folder, filename, suffixid.ToString("0000"), ext);
			}

			return outputfile;
		}


		/// <summary>
		/// 多次复制一个文件，以保证文件一定被复制走。在特殊情况下可能会用到。
		/// </summary>
		/// <param name="infile"></param>
		/// <param name="outfile"></param>
		/// <param name="totalTimes"></param>
		/// <returns></returns>
		public static bool MultipleCopyFile(string infile, string outfile, int totalTimes = 5)
		{
			// Try  times at most. Note: input file should be existed and outputfile should not. 
			int copyTimes = 0;

			while (true)
			{
				File.Copy(infile, outfile);
				Thread.Sleep(100);
				if (File.Exists(outfile) || copyTimes++ > totalTimes)
					break;
			}

			return File.Exists(outfile);
		}



		/// <summary>
		/// Deletes the input file when backuping. Tries 5 times and adds to logs if fails.
		/// </summary>
		/// <param name="inputfile"></param>
		public static bool DeleteFile(string inputfile, int totalTimes = 5)
		{
			// Delete 5 times at most.
			int deleteTimes = 0;
			while (true)
			{
				File.Delete(inputfile);
				Thread.Sleep(100);

				if (!File.Exists(inputfile) || deleteTimes++ > totalTimes)
					break;
			}

			return !File.Exists(inputfile);
		}


		/// <summary>
		/// 给定路径，获得下面指定层数的文件。
		/// </summary>
		/// <param name="dir">指定的路径。</param>
		/// <param name="lv">子目录层数，最少为0，即只获得当前目录下文件。</param>
		/// <returns></returns>
		public string[] GetFile(string dir, int lv)
		{
			List<string> list = new List<string>();
			list.AddRange(Directory.GetFiles(dir));
			if (lv > 0)
			{
				string[] dirs = Directory.GetDirectories(dir);

				foreach (string s in dirs)
				{
					list.AddRange(GetFile(s, lv - 1));
				}
			}

			return list.ToArray();
		}

		/// <summary>
		/// 删除指定文件夹下的所有文件，通过递归实现。
		/// </summary>
		/// <param name="path"></param>
		public static void DeleteFiles(string path)
		{
			//删除指定文件夹下的所有文件。
			string[] files = Directory.GetFiles(path);
			foreach (string s in files)
			{
				try
				{
					File.Delete(s);
				}
				catch { }
			}

			//删除文件夹。
			string[] folders = Directory.GetDirectories(path);
			foreach (string fd in folders)
			{
				try
				{
					DeleteFiles(fd);
					Directory.Delete(fd);
				}
				catch { }
			}
		}

		/// <summary>
		///  infile: d:\data\2018\01\de_01.txt
		///  inroot: d:\data
		///  outdir: e:\out
		///  outfile: e:\out\2018\01\de_01.txt
		/// </summary>
		/// <param name="infile"></param>
		/// <param name="inroot"></param>
		/// <param name="outdir"></param>
		/// <returns></returns>
		public static string GetOutFolder(string infile, string inroot, string outdir)
		{
			return Path.Combine(outdir, infile.Substring(inroot.Length).Replace(":", ""));
		}
	}
}
